#include <GL/glut.h>
#include <cstdlib>
#include <cmath>
#include <iostream>

#define ROUND_PRECISION 50
#define CIRC 2 * M_PI
#define DTHETA CIRC / ROUND_PRECISION
#define NCOLS_BOARD 5
#define NLINS_BOARD 5
#define X0 -50.0f
#define X1 50.0f
#define Y0 -50.0f
#define Y1 50.0f
#define BOARD_PIECE_WIDTH (X1-X0)/NCOLS_BOARD
#define BOARD_PIECE_HEIGHT (Y1-Y0)/NLINS_BOARD

GLfloat ratio = 1.0f;

// intensidade das componentes de cor nos tipos de luz, ou seja, cor de cada luz
GLfloat AMB[4] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat DIF[4] = { 0.9f, 0.9f, 0.9f, 1.0f };
GLfloat ESP[4] = { 1.0f, 1.0f, 1.0f, 1.0f };

// cores
GLfloat BRANCO[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat CINZA1[4] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat CINZA2[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat CINZA3[4] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat CINZA4[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
GLfloat CINZA5[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat CINZA6[4] = { 0.6f, 0.6f, 0.6f, 1.0f };
GLfloat CINZA7[4] = { 0.7f, 0.7f, 0.7f, 1.0f };
GLfloat AMARELO[4] = { 1.0f, 1.0f, 0.0f, 1.0f };
GLfloat AZUL[4] = { 0.0f, 0.0f, 0.5f, 1.0f };
GLfloat VERMELHO[4] = { 0.5f, 0.0f, 0.0f, 1.0f };
GLfloat VERDE[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
GLfloat AMARELOESC[4] = { 0.2f, 0.2f, 0.0f, 1.0f };
GLfloat AZULESC[4] = { 0.0f, 0.0f, 0.2f, 1.0f };
GLfloat VERMELHOESC[4] = { 0.2f, 0.0f, 0.0f, 1.0f };
GLfloat VERDEESC[4] = { 0.0f, 0.2f, 0.0f, 1.0f };
GLfloat PRETO[4] = { 0.1f, 0.1f, 0.1f, 1.0f };

//posicoes das fontes de luz
GLfloat POS[2][4] = { { 50.0f, 50.0f, 100.0f, 1.0f }, { -50.0f, -50.0f, 20.0f, 1.0f } };

GLfloat COR[4][4] = { { 1.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.5f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f,
		0.5f, 1.0f } };
int cor = 0;

float headAngle = 0;
float eyePositionModifier = 1;
float eyePositionX = 80;
float eyePositionY = 80;
float eyePositionZ = 80;
float r2x = 0;
float r2y = 0;
float r2z = 0;
float r2Angle = 0;
GLfloat rotationAngle = 170;
GLfloat footAngle = 0;

void translateColor(int r, int g, int b, GLfloat array[]) {
	array[0] = r / 255.0;
	array[1] = g / 255.0;
	array[2] = b / 255.0;
	array[3] = 1.0;
}

struct vertex {
	GLfloat coordinates[4];

	vertex(GLfloat x = 0, GLfloat y = 0, GLfloat z = 0, GLfloat* mycolor = BRANCO) {
		set(x, y, z);
	}
	vertex(const GLfloat *u, GLfloat* mycolor = BRANCO) {
		for (int k = 0; k < 4; k++) {
			coordinates[k] = u[k];
		}
	}
	vertex(const vertex &r) {
		set(r);
	}
	void set(GLfloat x, GLfloat y, GLfloat z) {
		coordinates[0] = x;
		coordinates[1] = y;
		coordinates[2] = z;
		coordinates[3] = 1;
	}
	void set(const vertex &r) {
		for (int k = 0; k < 4; k++) {
			coordinates[k] = r.coordinates[k];
		}
	}
	void draw() {
		glVertex4fv(coordinates);
	}
};

struct vec {
	GLfloat tipCoordinates[4];
	//origin is 0,0,0

	vec(GLfloat cx, GLfloat cy, GLfloat cz) {
		tipCoordinates[0] = cx;
		tipCoordinates[1] = cy;
		tipCoordinates[2] = cz;
		tipCoordinates[3] = 1;
	}
	vec(GLfloat* u) {
		for (int k = 0; k < 4; k++)
			tipCoordinates[k] = u[k];
	}
	vec(vertex A, vertex B) {
		for (int k = 0; k < 3; k++)
			tipCoordinates[k] = B.coordinates[k] - A.coordinates[k];
		tipCoordinates[3] = 1;
	}
	vec dot(vec &r) {
		GLfloat m[3][3] = { { tipCoordinates[0] /*0,0*/, tipCoordinates[1] /*0,1*/, tipCoordinates[2] /*0,2*/}, {
				r.tipCoordinates[0]/*1,0*/, r.tipCoordinates[1]/*1,1*/, r.tipCoordinates[2] }/*1,2*/, { 1, 1, 1 } };
		GLfloat i = m[0][1] * m[1][2] - m[0][2] * m[1][1];
		GLfloat j = -m[0][0] * m[1][2] + m[0][2] * m[1][0];
		GLfloat k = m[0][0] * m[1][1] - m[0][1] * m[1][0];
		return vec(i, j, k);
	}
	GLfloat modus() {
		return sqrt(pow(tipCoordinates[0], 2.0) + pow(tipCoordinates[1], 2.0) + pow(tipCoordinates[2], 2.0))
				/ tipCoordinates[3];
	}
	vec unit() {
		GLfloat m = modus();
		return vec(tipCoordinates[0] / m, tipCoordinates[1] / m, tipCoordinates[2] / m);
	}
};

struct mesh {
	vertex vertexes[4];
	mesh(vertex a, vertex b, vertex c, vertex d) {
		vertexes[0].set(a);
		vertexes[1].set(b);
		vertexes[2].set(c);
		vertexes[3].set(d);
	}
	vec normal() {
		vec u = vec(vertexes[0], vertexes[1]).unit();
		vec w = vec(vertexes[1], vertexes[2]).unit();
		//return w.dot(u); original ricardo
		return u.dot(w);
	}
	void draw() {
		glBegin(GL_POLYGON);
		glNormal3fv(normal().tipCoordinates);
		for (int k = 0; k < 4; k++)
			vertexes[k].draw();
		glEnd();
	}
};

struct drawable {
	GLfloat color[4];
	virtual ~drawable() {
	}
	virtual void draw() = 0;
	virtual void setColor(GLfloat r, GLfloat g, GLfloat b) {
		color[0] = r;
		color[1] = g;
		color[2] = b;
		color[3] = 1.0;
	}
	virtual void setColor(int r, int g, int b) {
		translateColor(r, g, b, color);
	}
};

struct openCylinder: drawable {
	float height, width;
	openCylinder(float h, float w, GLfloat cor[] = CINZA4) {
		color[0] = cor[0];
		color[1] = cor[1];
		color[2] = cor[2];
		color[3] = cor[3];
		height = h;
		width = w;

	}
	openCylinder(const openCylinder& c) {
		color[0] = c.color[0];
		color[1] = c.color[1];
		color[2] = c.color[2];
		color[3] = c.color[3];
		height = c.height;
		width = c.width;

	}
	virtual void draw() {
		glPushMatrix();
		glColor4fv(color);
		gluCylinder(gluNewQuadric(), width, width, height, ROUND_PRECISION, ROUND_PRECISION);
		glPopMatrix();
	}
};

struct cylinder: openCylinder {
	cylinder(float h, float w, GLfloat cor[] = CINZA4) :
		openCylinder(h, w, cor) {
	}
	virtual void draw() {
		glPushMatrix();
		glColor4fv(color);
		gluDisk(gluNewQuadric(), 0, width, ROUND_PRECISION, ROUND_PRECISION);
		gluCylinder(gluNewQuadric(), width, width, height, ROUND_PRECISION, ROUND_PRECISION);
		glTranslatef(0, 0, height);
		gluDisk(gluNewQuadric(), 0, width, ROUND_PRECISION, ROUND_PRECISION);
		glPopMatrix();
	}
};

struct sphere: drawable {
	float radius;
	sphere(float r, GLfloat cor[] = CINZA4) {
		color[0] = cor[0];
		color[1] = cor[1];
		color[2] = cor[2];
		color[3] = cor[3];
		radius = r;

	}
	sphere(const sphere& c) {
		color[0] = c.color[0];
		color[1] = c.color[1];
		color[2] = c.color[2];
		color[3] = c.color[3];
		radius = c.radius;

	}
	virtual void draw() {
		glPushMatrix();
		glColor4fv(color);
		gluSphere(gluNewQuadric(), radius, ROUND_PRECISION, ROUND_PRECISION);
		glPopMatrix();
	}
};

struct parallelepiped: drawable {
	float height, width, depth;
	parallelepiped(float h, float w, float d, GLfloat cor[] = CINZA4) {
		color[0] = cor[0];
		color[1] = cor[1];
		color[2] = cor[2];
		color[3] = cor[3];
		height = h;
		width = w;
		depth = d;
	}
	parallelepiped(const parallelepiped& c) {
		color[0] = c.color[0];
		color[1] = c.color[1];
		color[2] = c.color[2];
		color[3] = c.color[3];
		height = c.height;
		width = c.width;
		depth = c.depth;
	}
	virtual void draw() {
		vertex v1 = vertex(+height / 2, -width / 2, 0, color);
		vertex v2 = vertex(-height / 2, -width / 2, 0, color);
		vertex v3 = vertex(-height / 2, +width / 2, 0, color);
		vertex v4 = vertex(+height / 2, +width / 2, 0, color);

		vertex v5 = vertex(+height / 2, -width / 2, +depth, color);
		vertex v6 = vertex(-height / 2, -width / 2, +depth, color);
		vertex v7 = vertex(-height / 2, +width / 2, +depth, color);
		vertex v8 = vertex(+height / 2, +width / 2, +depth, color);

		mesh m1 = mesh(v1, v2, v3, v4);
		mesh m2 = mesh(v5, v6, v7, v8);
		mesh m3 = mesh(v1, v2, v6, v5);
		mesh m4 = mesh(v4, v3, v7, v8);
		mesh m5 = mesh(v1, v4, v8, v5);
		mesh m6 = mesh(v2, v3, v7, v6);

		glPushMatrix();
		glColor4fv(color);
		m1.draw();
		m2.draw();
		m3.draw();
		m4.draw();
		m5.draw();
		m6.draw();
		glPopMatrix();
	}
};

struct frustum: drawable {
	float heightU, widthU, heightD, widthD, depth;
	frustum(float hu, float wu, float hd, float wd, float dep, GLfloat cor[] = CINZA4) {
		color[0] = cor[0];
		color[1] = cor[1];
		color[2] = cor[2];
		color[3] = cor[3];
		heightU = hu;
		widthU = wu;
		heightD = hd;
		widthD = wd;
		depth = dep;
	}
	frustum(const frustum& c) {
		color[0] = c.color[0];
		color[1] = c.color[1];
		color[2] = c.color[2];
		color[3] = c.color[3];
		heightU = c.heightU;
		widthU = c.widthU;
		heightD = c.heightD;
		widthD = c.widthD;
		depth = c.depth;
	}
	virtual void draw() {
		vertex v1 = vertex(+heightD / 2, -widthD / 2, -depth / 2, color);
		vertex v2 = vertex(-heightD / 2, -widthD / 2, -depth / 2, color);
		vertex v3 = vertex(-heightD / 2, +widthD / 2, -depth / 2, color);
		vertex v4 = vertex(+heightD / 2, +widthD / 2, -depth / 2, color);

		vertex v5 = vertex(+heightU / 2, -widthU / 2, +depth / 2, color);
		vertex v6 = vertex(-heightU / 2, -widthU / 2, +depth / 2, color);
		vertex v7 = vertex(-heightU / 2, +widthU / 2, +depth / 2, color);
		vertex v8 = vertex(+heightU / 2, +widthU / 2, +depth / 2, color);

		mesh m1 = mesh(v1, v2, v3, v4);
		mesh m2 = mesh(v5, v6, v7, v8);
		mesh m3 = mesh(v1, v2, v6, v5);
		mesh m4 = mesh(v4, v3, v7, v8);
		mesh m5 = mesh(v1, v4, v8, v5);
		mesh m6 = mesh(v2, v3, v7, v6);

		glPushMatrix();
		glColor4fv(color);
		m1.draw();
		m2.draw();
		m3.draw();
		m4.draw();
		m5.draw();
		m6.draw();
		glPopMatrix();
	}
};

struct crown: drawable {
	float rIn, rOut, distance;
	crown(float ri, float ro, float d, GLfloat cor[] = CINZA4) {
		color[0] = cor[0];
		color[1] = cor[1];
		color[2] = cor[2];
		color[3] = cor[3];
		rIn = ri;
		rOut = ro;
		distance = d;
	}
	crown(const crown& c) {
		color[0] = c.color[0];
		color[1] = c.color[1];
		color[2] = c.color[2];
		color[3] = c.color[3];
		rIn = c.rIn;
		rOut = c.rOut;
		distance = c.distance;
	}
	virtual void draw() {
		glPushMatrix();
		glColor4fv(color);

		float i;
		for (i = 0; i < CIRC; i += DTHETA) {
			vertex ext = vertex(rOut * cos(i), rOut * sin(i), 0);
			vertex intern = vertex(rIn * cos(i), rIn * sin(i), -distance);
			vertex intern2 = vertex(rIn * cos(i + DTHETA), rIn * sin(i + DTHETA), -distance);
			vertex ext2 = vertex(rOut * cos(i + DTHETA), rOut * sin(i + DTHETA), 0);
			mesh(ext, intern, intern2, ext2).draw();
		}

		glPopMatrix();
	}
};

void init() {
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHT1);
	glEnable(GL_DEPTH_TEST);

	glEnable(GL_COLOR_MATERIAL);
	glShadeModel(GL_SMOOTH);

	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, AMB);
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);

	for (int i = 0; i < 2; i++) {
		glLightfv(GL_LIGHT0 + i, GL_AMBIENT, AMB);
		glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, DIF);
		glLightfv(GL_LIGHT0 + i, GL_SPECULAR, ESP);
		glLightfv(GL_LIGHT0 + i, GL_POSITION, POS[i]);
	}

	glMaterialfv(GL_FRONT, GL_AMBIENT, AMB);
	glMateriali(GL_FRONT, GL_SHININESS, 7);
}

void resize(int w, int h) {
	if (h == 0)
		h = 1;
	glViewport(0, 0, w, h);
	ratio = (GLfloat) w / (GLfloat) h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(40, ratio, 0.5, 500.0);
}

void drawChessBoard() {
	for (int col = 0; col < NCOLS_BOARD; col++) {
		GLfloat x = X0 + BOARD_PIECE_WIDTH * col;
		for (int lin = 0; lin < NLINS_BOARD; lin++) {
			GLfloat y = Y0 + BOARD_PIECE_HEIGHT * lin;
			glBegin(GL_POLYGON);
			if ((col + lin) % 2 == 0)
				glColor4fv(BRANCO);
			else
				glColor4fv(CINZA2);
			glNormal3f(0, 0, 1);
			glVertex3f(x, y, 0.0f);
			glVertex3f(x + BOARD_PIECE_WIDTH, y, 0.0f);
			glVertex3f(x + BOARD_PIECE_WIDTH, y + BOARD_PIECE_HEIGHT, 0.0f);
			glVertex3f(x, y + BOARD_PIECE_HEIGHT, 0.0f);
			glEnd();
		}
	}
}

void mostraOrigem(int escuro = 0) {
	if (!escuro) {
		sphere(2, VERMELHO).draw();
		glTranslatef(15, 0, 0);
		sphere(2, AZUL).draw(); // X AZUL
		glTranslatef(-15, 15, 0);
		sphere(2, AMARELO).draw(); // Y AMARELO
		glTranslatef(0, -15, 15);
		sphere(2, VERDE).draw(); // Z VERDE
		glTranslatef(0, 0, -15);
	} else {
		sphere(2, VERMELHOESC).draw();
		glTranslatef(12, 0, 0);
		sphere(2, AZULESC).draw(); // X AZUL
		glTranslatef(-12, 12, 0);
		sphere(2, AMARELOESC).draw(); // Y AMARELO
		glTranslatef(0, -12, 12);
		sphere(2, VERDEESC).draw(); // Z VERDE
		glTranslatef(0, 0, -12);
	}
}

void drawRightArm(float x = 0, float y = 0, float z = 0, float angleVectorX = 0, float angleVectorY = 0,
		float angleVectorZ = 0, float angle = 0) {
	glPushMatrix();
	glRotatef(15, 1, 0, 0);
	glRotatef(90, angleVectorX, angleVectorY + 1, angleVectorZ);

	glTranslatef(-z, y, x);
	cylinder(1.9, 2.5, CINZA3).draw();
	cylinder(1.5, 4, CINZA4).draw();

	glTranslatef(3, 0, 0);
	parallelepiped(6, 8, 1.5, CINZA4).draw();

	glTranslatef(7, 0, 0);
	parallelepiped(20, 5, 1.5, CINZA4).draw();
	parallelepiped(20, 3, 1.9, AZULESC).draw();

	glTranslatef(10, 0, 0);
	cylinder(1.5, 2.47, CINZA4).draw();

	//mostraOrigem(1);
	glTranslatef(-14, -2.5, 0);
	glRotatef(45, 0, 0, 1);
	parallelepiped(2, 2, 1.5, CINZA4).draw();

	glRotatef(-45, 0, 0, 1);
	glTranslatef(0, 5, 0);
	glRotatef(45, 0, 0, 1);
	parallelepiped(2, 2, 1.5, CINZA4).draw();

	glPopMatrix();
}

void drawLeftArm(float x = 0, float y = 0, float z = 0, float angleVectorX = 0, float angleVectorY = 0,
		float angleVectorZ = 0, float angle = 0) {
	glPushMatrix();
	glRotatef(180, 0, 0, 1);
	glRotatef(-30, 1, 0, 0);
	drawRightArm(x, -y, z, angleVectorX, angleVectorY, angleVectorZ, angle);
	glPopMatrix();
}

void drawFlashLight() {
	glPushMatrix();
	glRotatef(-10, 1, 0, 0);
	glRotatef(-25, 0, 1, 0);
	glTranslatef(0, 0, 10.0);
	frustum(4, 3, 5, 4, 1, AZULESC).draw();

	glTranslatef(0, 0, 1);
	glColor4fv(PRETO);
	gluDisk(gluNewQuadric(), 0, 1, ROUND_PRECISION, ROUND_PRECISION);
	glTranslatef(0, 0, -1);

	//mostraOrigem(1);

	glTranslatef(0, 0, -10.0);
	glRotatef(12, 1, 0, 0);
	glTranslatef(1, 0, 10.0);
	//mostraOrigem();
	frustum(2, 1.5, 2.5, 2, 1, AZULESC).draw();

	glTranslatef(0, 0, .8);
	glColor4fv(COR[cor++ % 4]);
	gluDisk(gluNewQuadric(), 0, 0.5, ROUND_PRECISION, ROUND_PRECISION);
	glTranslatef(0, 0, -0.8);

	glPopMatrix();
}

void drawHead(float x = 0, float y = 0, float z = 0, float angle = 0) {
	glPushMatrix();
	glTranslatef(x, y, z);
	glRotatef(-30, 1, 0, 0);

	if (angle) {
		glRotatef(angle, 0, 0, 1);
	}

	sphere(9.9, CINZA1).draw();

	glRotatef(85, 1, 0, 0);
	glRotatef(25, 0, 1, 0);
	glTranslatef(0, -2, 0);
	openCylinder(11, 1, CINZA2).draw();

	glTranslatef(0, 0, 10.5);
	glColor4fv(AMARELO);
	gluDisk(gluNewQuadric(), 0, 1, ROUND_PRECISION, ROUND_PRECISION);
	glTranslatef(0, 0, -10.5);

	drawFlashLight();
	glTranslatef(0, 2, 0);

	glRotatef(-100, 1, 0, 0);
	openCylinder(11, 1, CINZA2).draw();
	glTranslatef(0, 0, 10.5);
	glColor4fv(AZULESC);
	gluDisk(gluNewQuadric(), 0, 1, ROUND_PRECISION, ROUND_PRECISION);
	glTranslatef(0, 0, -10.5);

	glRotatef(-60, 1, 0, 0);
	glRotatef(30, 0, 1, 0);
	openCylinder(11, 1, CINZA2).draw();
	glTranslated(0, 0, 10.5);
	glColor4f(0,0,0,1);
	gluDisk(gluNewQuadric(), 0, 1, ROUND_PRECISION, ROUND_PRECISION);
	glTranslated(0, 0, -10.5);

	glPopMatrix();
}

void drawBody(float x = 0, float y = 0, float z = 0, float angleVectorX = 0, float angleVectorY = 0,
		float angleVectorZ = 0, float angle = 0) {
	glPushMatrix();
	glTranslatef(x, y, z);
	glRotatef(-30, 1, 0, 0);
	cylinder(20, 10, CINZA4).draw();
	crown(8, 10, 2, CINZA3).draw();

	glTranslatef(0, 0, 20);
	cylinder(5, 10, CINZA1).draw();
	glTranslatef(0, 0, -20);

	glTranslatef(0, -10, 5);
	parallelepiped(3, 1, 10, AZULESC).draw();
	glPopMatrix();
}

void drawRightFoot(float x = 0, float y = 0, float z = 0, float angleVectorX = 0, float angleVectorY = 0,
		float angleVectorZ = 0, float angle = 0) {
	glPushMatrix();

	glTranslatef(x, y, z);
	frustum(4, 7, 6, 10, 5, CINZA4).draw();

	glPopMatrix();
}

void drawLeftFoot(float x = 0, float y = 0, float z = 0, float angleVectorX = 0, float angleVectorY = 0,
		float angleVectorZ = 0, float angle = 0) {
	glPushMatrix();
	drawRightFoot(-x, y, z, angleVectorX, angleVectorY, angleVectorZ, angle);
	glPopMatrix();
}

void drawCenterFoot(float x = 0, float y = 0, float z = 0, float angle = 0) {
	glPushMatrix();
	glTranslatef(x, y, z);
	if (angle) {
		glRotatef(angle, 0, 0, 1);
	}
	frustum(4, 6, 6, 10, 5, CINZA4).draw();
	if (angle) {
		glRotatef(-angle, 0, 0, 1);
	}
	glRotated(90, 0, 1, 0);
	glRotated(-30, 0, 0, 1);
	glTranslatef(-10, 0, -0.6);
	parallelepiped(10, 5, 1.5, CINZA4).draw();

	glTranslatef(5, 0, 0);
	cylinder(1.5, 2.47, CINZA4).draw();
	glPopMatrix();
}

void drawR2(float x = 0, float y = 0, float z = 0, float angle = 0) {
	if (angle) {
		glTranslatef(-10, -4, 0);
		//glTranslatef(-10.7, +2, -5);
		//mostraOrigem();
		glRotatef(angle, 0, 0, 1);
		//glTranslatef(10.7, -2, 5);
		glTranslatef(+10, +4, 0);
	}
	glTranslatef(x, y, z);
	drawRightArm(0, 0, 30);
	drawRightFoot(.7, -2, 5);
	drawLeftArm(20, 0, 30);
	drawLeftFoot(20.7, -2, 5);
	drawHead(-10, -4, 36.67, headAngle);
	drawBody(-10, -16.5, 15);
	drawCenterFoot(-10, -22, 5, footAngle);
}

void display() {
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(eyePositionX / eyePositionModifier, eyePositionY / eyePositionModifier,
			eyePositionZ / eyePositionModifier, 0, 0, 20, 0, 0, 1);
	glRotatef(rotationAngle, 0, 0, 1);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	drawChessBoard();

	//	cylinder(10, 20).draw();
	//	glTranslatef(30, 30, 0);
	//	openCylinder(10, 20).draw();
	//	glTranslatef(-60, -60, 10);
	//	sphere(10).draw();
	//	glTranslatef(30, 30, 20);
	//	parallelepiped(10, 20, 20).draw();
	//	glTranslatef(30, 30, 0);
	//	frustum(10, 15, 20, 25, 10).draw();
	//	glTranslatef(-60, -60, 0);
	//	crown(10, 20, 10).draw();

	drawR2(r2x, r2y, r2z, r2Angle);
	glutSwapBuffers();
}

void timer(int x) {
	//rotationAngle += 0.72;

	glutPostRedisplay();
	glutTimerFunc(1500, timer, x);
}

//----------------------------Keyboard-------------------------------------------------------------

void keyboard(unsigned char key, int x, int y) {
	switch (key) {
	case 'w':
		if (eyePositionModifier < 2) {
			eyePositionModifier += 0.05;
		}
		glutPostRedisplay();
		break;
	case 'a':
		rotationAngle += 1;
		glutPostRedisplay();
		break;
	case 's':
		if (eyePositionModifier > 0.9) {
			eyePositionModifier -= 0.05;
		}
		glutPostRedisplay();
		break;
	case 'd':
		rotationAngle -= 1;
		glutPostRedisplay();
		break;
	case 'q':
		headAngle -= 2;
		glutPostRedisplay();
		break;
	case 'e':
		headAngle += 2;
		glutPostRedisplay();
		break;
		// Backspace
	case 8:
		break;
		// Enter
	case 13:
		break;
		// Escape
	case 27:
		break;
		// Delete
	case 127:
		break;
	default:
		break;
	}
	int mod = glutGetModifiers();
	switch (mod) {
	case GLUT_ACTIVE_CTRL:
		break;
	case GLUT_ACTIVE_SHIFT:
		break;
	case GLUT_ACTIVE_ALT:
		break;
	}
}
void keyboardup(unsigned char key, int x, int y) {
	if (key == 'a') {
	}
}
void special(int key, int x, int y) {
	switch (key) {
	case GLUT_KEY_F2:
		break;
	case GLUT_KEY_LEFT:
		r2Angle -= 1;
		if (footAngle > -35) {
			footAngle -= 10;
		}
		glutPostRedisplay();
		break;
	case GLUT_KEY_RIGHT:
		if (footAngle < 35) {
			footAngle += 10;
		}
		r2Angle += 1;
		glutPostRedisplay();
		break;
	case GLUT_KEY_UP:
		if (footAngle < -2 || footAngle > 2) {
			footAngle -= footAngle / 2;
		}
		if (r2y > -10) {
			r2y -= 0.5;
		}
		glutPostRedisplay();
		break;
	case GLUT_KEY_DOWN:
		if (footAngle < -2 || footAngle > 2) {
			footAngle -= footAngle / 2;
		}
		if (r2y < 10) {
			r2y += 0.5;
		}
		glutPostRedisplay();
		break;
	case GLUT_KEY_INSERT: {
		int modifiers = glutGetModifiers();
		if (modifiers == (GLUT_ACTIVE_CTRL | GLUT_ACTIVE_ALT)) {
		} else if ((modifiers & GLUT_ACTIVE_CTRL) && (modifiers & GLUT_ACTIVE_ALT)) {
		}
		break;
	}

	}
}

int main() {
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowPosition(5, 5);
	glutInitWindowSize(700, 700);
	glutCreateWindow("R2D2");
	glutDisplayFunc(display);
	glutReshapeFunc(resize);
	glutKeyboardFunc(keyboard);
	glutKeyboardUpFunc(keyboardup);
	glutSpecialFunc(special);
	glutTimerFunc(200, timer, 1);
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	init();
	glutMainLoop();
	return 0;
}
